#include "SubsystemNoise.h"
#include "INoiseListener.hpp"
#include "Components/ComponentBody.h"
#include "ComponentNoiseListener.h"

#include "Subsystems/SubsystemTerrain.h"
#include "Subsystems/SubsystemBodies.h"

#include "GameRegistry.hpp"
#include "GameSingleton.h"
#include "Managers/BlocksManager.h"

namespace PocketSurvival
{
    void SubsystemNoise::makeNoise(const Vector3& position, float loudness, float range)
    {
        makeNoisePublic(entt::null, position, loudness, range);
    }

    void SubsystemNoise::makeNoise(ComponentBody *sourceBody, float loudness, float range)
    {
        if (sourceBody != nullptr)
        {
            Vector3 position;
            sourceBody->getPosition(position);

            makeNoisePublic(sourceBody->entity, position, loudness, range);
        }
    }

    void SubsystemNoise::makeNoisePublic(entt::entity sourceEntity, const Vector3& position, float loudness, float range)
    {
        float num = range * range;
        std::vector<ComponentBody *> bodyVec;
        subsystemBodies->findBodiesAroundPoint(Vector2(position.posX, position.posZ), range, bodyVec);
        for (ComponentBody *body : bodyVec)
        {
            Vector3 bodyPosition;
            body->getPosition(bodyPosition);

            if (body->entity != sourceEntity && Vector3::DistanceSquared(bodyPosition, position) < num)
            {
                ComponentNoiseListener **noisePtr = GameSingleton::gameRegistry->try_get<ComponentNoiseListener*>(body->entity);
                ComponentNoiseListener *noiseListener = (noisePtr != nullptr) ? (*noisePtr) : nullptr;
                if (noiseListener != nullptr)
                {
                    for (INoiseListener *item : noiseListener->noiseVec)
                    {
                        item->hearNoise(body, position, loudness);
                    }
                }
            }
        }
    }

    static const std::string subsystemName = "Noise";
    const std::string &SubsystemNoise::getName() const
    {
        return subsystemName;
    }
    void SubsystemNoise::load(const nlohmann::json &json)
    {
        subsystemBodies = GameSingleton::singletonPtr->getSingleton<SubsystemBodies>();
    }

} // namespace PocketSurvival
